<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Component Example 5: Slot 用法演示</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        
        .demo-section {
            background: white;
            margin: 20px 0;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        .controls {
            margin: 20px 0;
            padding: 15px;
            background-color: #e9ecef;
            border-radius: 5px;
        }
        
        .controls button {
            margin: 0 10px;
            padding: 8px 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        
        .controls button:hover {
            background-color: #0056b3;
        }
        
        .slot-demo {
            border: 2px dashed #007bff;
            padding: 15px;
            margin: 10px 0;
            border-radius: 5px;
        }
        
        .named-slot {
            background-color: #f8f9fa;
            padding: 10px;
            margin: 5px 0;
            border-left: 4px solid #007bff;
        }
        
        .fallback-content {
            color: #6c757d;
            font-style: italic;
        }
        
        .slot-info {
            background-color: #e7f3ff;
            padding: 10px;
            border-radius: 4px;
            margin: 10px 0;
            border-left: 4px solid #007bff;
        }
    </style>
</head>
<body>
    <h1>Web Component Slot 用法演示</h1>
    
    <div class="demo-section">
        <h2>1. 基础 Slot（默认插槽）</h2>
        <div class="slot-info">
            <strong>说明：</strong>默认插槽允许你在自定义元素中插入任意内容
        </div>
        
        <my-card>
            <h3>这是插入到默认插槽的内容</h3>
            <p>你可以在这里放置任何HTML内容，包括文本、图片、按钮等。</p>
            <button onclick="alert('按钮被点击了！')">点击我</button>
        </my-card>
    </div>

    <div class="demo-section">
        <h2>2. 命名插槽（Named Slots）</h2>
        <div class="slot-info">
            <strong>说明：</strong>命名插槽允许你在特定位置插入特定内容
        </div>
        
        <my-article>
            <h2 slot="title">文章标题</h2>
            <p slot="content">这是文章的主要内容。你可以在这里放置很长的文本内容。</p>
            <div slot="footer">
                <span>作者：张三</span>
                <span>发布时间：2024-01-01</span>
            </div>
        </my-article>
    </div>

    <div class="demo-section">
        <h2>3. 带默认内容的插槽</h2>
        <div class="slot-info">
            <strong>说明：</strong>当插槽完全为空时，会显示默认内容。注意：HTML注释也被认为是内容   <ul>
              <li>第一个：有内容，显示自定义内容</li>
              <li>第二个：有注释，注释被认为是内容，所以不显示默认内容</li>
              <li>第三个：完全空元素，显示默认内容</li>
          </ul>        </div>
        
        <my-card-with-fallback>
            <p>这个内容会替换默认内容</p>
        </my-card-with-fallback>
        
        <my-card-with-fallback>
            <!-- 注释也被认为是内容，所以不会显示默认内容 -->
        </my-card-with-fallback>
        
        <my-card-with-fallback></my-card-with-fallback>
        
    </div>

    <div class="demo-section">
        <h2>4. 动态 Slot 内容</h2>
        <div class="controls">
            <button onclick="updateSlotContent()">更新插槽内容</button>
            <button onclick="toggleSlot()">切换插槽内容</button>
        </div>
        
        <my-dynamic-card id="dynamic-card">
            <div slot="header">原始头部内容</div>
            <div slot="body">原始主体内容</div>
            <div slot="footer">原始底部内容</div>
        </my-dynamic-card>
    </div>

    <div class="demo-section">
        <h2>5. 插槽样式和事件</h2>
        <div class="slot-info">
            <strong>说明：</strong>插槽内容可以有自己的样式和事件处理
        </div>
        
        <my-styled-card>
            <div slot="header" style="background: linear-gradient(45deg, #ff6b6b, #4ecdc4); color: white; padding: 15px; border-radius: 5px;">
                <h3>渐变背景的头部</h3>
            </div>
            <div slot="content" style="padding: 20px;">
                <p>这是主体内容，可以有自己的样式。</p>
                <button onclick="this.style.backgroundColor='#28a745'; this.textContent='已点击'">
                    点击改变颜色
                </button>
            </div>
        </my-styled-card>
    </div>

    <script>
        // 1. 基础 Slot 组件
        class MyCard extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
            }

            connectedCallback() {
                this.shadowRoot.innerHTML = `
                    <style>
                        .card {
                            border: 1px solid #ddd;
                            border-radius: 8px;
                            padding: 20px;
                            margin: 10px 0;
                            background: white;
                            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                        }
                        .card-title {
                            color: #333;
                            margin-bottom: 10px;
                        }
                        ::slotted(*) {
                            margin: 5px 0;
                        }
                        ::slotted(button) {
                            background-color: #007bff;
                            color: white;
                            border: none;
                            padding: 8px 16px;
                            border-radius: 4px;
                            cursor: pointer;
                        }
                        ::slotted(button:hover) {
                            background-color: #0056b3;
                        }
                    </style>
                    <div class="card">
                        <div class="card-title">📋 卡片组件</div>
                        <slot></slot>
                    </div>
                `;
            }
        }

        // 2. 命名插槽组件
        class MyArticle extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
            }

            connectedCallback() {
                this.shadowRoot.innerHTML = `
                    <style>
                        .article {
                            border: 1px solid #e0e0e0;
                            border-radius: 8px;
                            overflow: hidden;
                            background: white;
                            margin: 10px 0;
                        }
                        .article-header {
                            background-color: #f8f9fa;
                            padding: 15px;
                            border-bottom: 1px solid #e0e0e0;
                        }
                        .article-content {
                            padding: 20px;
                            line-height: 1.6;
                        }
                        .article-footer {
                            background-color: #f8f9fa;
                            padding: 10px 15px;
                            border-top: 1px solid #e0e0e0;
                            font-size: 0.9em;
                            color: #666;
                        }
                        ::slotted([slot="title"]) {
                            margin: 0;
                            color: #333;
                        }
                        ::slotted([slot="content"]) {
                            margin: 0;
                        }
                        ::slotted([slot="footer"]) {
                            display: flex;
                            justify-content: space-between;
                        }
                    </style>
                    <article class="article">
                        <header class="article-header">
                            <slot name="title"></slot>
                        </header>
                        <div class="article-content">
                            <slot name="content"></slot>
                        </div>
                        <footer class="article-footer">
                            <slot name="footer"></slot>
                        </footer>
                    </article>
                `;
            }
        }

        // 3. 带默认内容的插槽组件
        class MyCardWithFallback extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
            }

            connectedCallback() {
                this.shadowRoot.innerHTML = `
                    <style>
                        .card {
                            border: 1px solid #ddd;
                            border-radius: 8px;
                            padding: 20px;
                            margin: 10px 0;
                            background: white;
                        }
                        .fallback {
                            color: #999;
                            font-style: italic;
                            text-align: center;
                            padding: 20px;
                        }
                    </style>
                    <div class="card">
                        <slot>
                            <div class="fallback">
                                🎯 这是默认内容，当没有提供插槽内容时会显示
                            </div>
                        </slot>
                    </div>
                `;
            }
        }

        // 4. 动态插槽组件
        class MyDynamicCard extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
            }

            connectedCallback() {
                this.shadowRoot.innerHTML = `
                    <style>
                        .dynamic-card {
                            border: 1px solid #ddd;
                            border-radius: 8px;
                            overflow: hidden;
                            background: white;
                            margin: 10px 0;
                        }
                        .header, .body, .footer {
                            padding: 15px;
                        }
                        .header {
                            background-color: #007bff;
                            color: white;
                        }
                        .footer {
                            background-color: #f8f9fa;
                            border-top: 1px solid #e0e0e0;
                        }
                    </style>
                    <div class="dynamic-card">
                        <div class="header">
                            <slot name="header"></slot>
                        </div>
                        <div class="body">
                            <slot name="body"></slot>
                        </div>
                        <div class="footer">
                            <slot name="footer"></slot>
                        </div>
                    </div>
                `;
            }
        }

        // 5. 样式化插槽组件
        class MyStyledCard extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
            }

            connectedCallback() {
                this.shadowRoot.innerHTML = `
                    <style>
                        .styled-card {
                            border: 1px solid #ddd;
                            border-radius: 8px;
                            overflow: hidden;
                            background: white;
                            margin: 10px 0;
                            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                        }
                        ::slotted([slot="header"]) {
                            margin: 0;
                        }
                        ::slotted([slot="content"]) {
                            margin: 0;
                        }
                        ::slotted(button) {
                            margin-top: 10px;
                        }
                    </style>
                    <div class="styled-card">
                        <slot name="header"></slot>
                        <slot name="content"></slot>
                    </div>
                `;
            }
        }

        // 注册自定义元素
        customElements.define('my-card', MyCard);
        customElements.define('my-article', MyArticle);
        customElements.define('my-card-with-fallback', MyCardWithFallback);
        customElements.define('my-dynamic-card', MyDynamicCard);
        customElements.define('my-styled-card', MyStyledCard);

        // 动态更新插槽内容的函数
        function updateSlotContent() {
            const card = document.getElementById('dynamic-card');
            const header = card.querySelector('[slot="header"]');
            const body = card.querySelector('[slot="body"]');
            const footer = card.querySelector('[slot="footer"]');
            
            header.innerHTML = `🔄 更新后的头部 - ${new Date().toLocaleTimeString()}`;
            body.innerHTML = `🔄 更新后的主体内容 - ${new Date().toLocaleTimeString()}`;
            footer.innerHTML = `🔄 更新后的底部 - ${new Date().toLocaleTimeString()}`;
        }

        function toggleSlot() {
            const card = document.getElementById('dynamic-card');
            const header = card.querySelector('[slot="header"]');
            const body = card.querySelector('[slot="body"]');
            const footer = card.querySelector('[slot="footer"]');
            
            if (header.textContent.includes('原始')) {
                header.innerHTML = '🔄 切换后的头部内容';
                body.innerHTML = '🔄 切换后的主体内容';
                footer.innerHTML = '🔄 切换后的底部内容';
            } else {
                header.innerHTML = '原始头部内容';
                body.innerHTML = '原始主体内容';
                footer.innerHTML = '原始底部内容';
            }
        }
    </script>
</body>
</html>
